package org.carl.code.main;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.io.file.PathUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import org.carl.code.General;
import org.carl.code.core.PlatForm;
import org.carl.code.util.GenerateUtil;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
import java.util.function.Consumer;

import static org.carl.code.Generate.upperFirstLatter;

/**
 * @author Administrator
 */
public class Main implements PlatForm {
    /**
     * 模板所在目录
     */
    private static final String TEMPLATE_DIR = DIR + File.separator + "template";
    /**
     * 模板输出目录
     */
    private static final String OUT_DIR = DIR + File.separator + "out";
    /**
     * 匹配的正则
     */
    private static final String REG = "[a-zA-Z0-9_一]+";

    /**
     * 模板项目中目录替换名
     */
    public static String replaceName,targetPkgName;
    /**
     * 忽略的文件夹和文件后缀
     */
    public static List<String> ignoreFileList,ignoreDirList;

    static {
        Console.log("欢迎使用代码生成器-code by 陈青松");
        Path tempPath = Paths.get(TEMPLATE_DIR);
        boolean exists = PathUtil.exists(tempPath, false);
        if (exists) {
            boolean dirEmpty = FileUtil.isDirEmpty(tempPath);
            if (dirEmpty) {
                exit();
            }
        } else {
            PathUtil.mkdir(tempPath);
            exit();
        }
        Path outDirPath = Paths.get(OUT_DIR);
        if (!PathUtil.exists(outDirPath, false)) {
            //生成输出目录
            PathUtil.mkdir(outDirPath);
        }
    }

    public static void exit() {
        Console.log("请将模板项目解压至:{}目录中,程序将在3秒后退出", TEMPLATE_DIR);
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(1);
    }

    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        Console.log("模板所在目录:{}", TEMPLATE_DIR);
        Console.log("代码输入目录:{}", OUT_DIR);
        String[] list = new File(TEMPLATE_DIR).list();
        //通用文件后缀
        List<String> generalFileExtList = StrUtil.split(CONFIG_SETTING.get("general.file.ext"),StrUtil.COMMA);
        //忽略的文件列表
        ignoreFileList = StrUtil.split(CONFIG_SETTING.get("ignore.file.ext"),StrUtil.COMMA);
        //忽略的文件夹列表
        ignoreDirList = StrUtil.split(CONFIG_SETTING.get("ignore.dir"),StrUtil.COMMA);
        for (String fileName : list) {
            //项目名称
            String project =null;
            do {
                Console.log("请输入请输入当前复制程序:{}的新项目名称",fileName);
                project=scanner.next();
            }while (!project.matches(REG));
            do{
                Console.log("请输入项目{}中需要替换包中的关键字",fileName);
                replaceName = scanner.next();
            }while (!replaceName.matches(REG));
            do{
                Console.log("请输入新项目{}核心包名关键字",project);
                targetPkgName = scanner.next();
            }while (!targetPkgName.matches(REG));
            //设置名称
            sourceName.set(replaceName.trim());
            targetName.set(targetPkgName.trim());
            Console.log("开始生成模板项目:{}", fileName);
            outProject(new File(TEMPLATE_DIR + File.separator + fileName), project,generalFileExtList);
            Console.log("模板项目:{}生成完成.", fileName);
            sourceName.remove();
            targetName.remove();
        }
        //生成zip包
        for(File file:new File(OUT_DIR).listFiles()){
            ZipUtil.zip(file);
        }
    }

    private static final void outProject(File sourceFile, String newProjName,List<String> generalFileExtList) {
        String oldProjName = FileNameUtil.mainName(sourceFile);
        if (StrUtil.isBlank(replaceName)) {
            replaceName = StrUtil.sub(oldProjName, 0, StrUtil.indexOf(oldProjName, '-'));
        }
        //创建父目录
        String outDir = OUT_DIR + File.separator + newProjName;
        FileUtil.mkdir(outDir);
        Consumer<File> consumer = file -> {
            //提取文件目录
            String dir = StrUtil.sub(file.toString(), sourceFile.toString().length() + 1, file.toString().lastIndexOf(File.separator));
            //文件目录替换
            dir = StrUtil.replace(dir, replaceName, targetName.get());
            //目标文件
            File targetFile=new File(outDir + File.separator + (StrUtil.endWith(dir, File.separator) ? dir : (dir + File.separator)) + getFileName(file, replaceName, targetName.get()));
            if(extInList(FileNameUtil.getName(targetFile),generalFileExtList)){
                new General(file,targetFile).generate();
            }else{
                try {
                    GenerateUtil.generate(file, targetFile);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        };
        walkFiles(sourceFile, consumer, consumer);
    }
    private static boolean extInList(String fileName,List<String> extList){
        Optional<String> optional = extList.stream().filter(ext -> StrUtil.endWith(fileName.toLowerCase(), ext)).findFirst();
        return optional.isPresent();
    }

    private static String getFileName(File file, String replaceName, String projectNamePre) {
        //读取文件名称
        String oldFileName = FileNameUtil.getName(file);
        String newFileName = null;
        //需要改首字母大写的文件
        if (oldFileName.startsWith(upperFirstLatter(replaceName))) {
            newFileName = file.getName().startsWith(StrUtil.DOT) ? file.getName() : oldFileName.replaceAll(upperFirstLatter(replaceName), upperFirstLatter(projectNamePre));
        } else {
            newFileName = file.getName().startsWith(StrUtil.DOT) ? file.getName() : oldFileName.replaceAll(replaceName, projectNamePre);
        }
        return newFileName;
    }

    /**
     * 递归处理目录
     *
     * @param file
     * @param dirConsumer
     * @param fileConsumer
     */
    public static void walkFiles(File file, Consumer<File> dirConsumer, Consumer<File> fileConsumer) {
        //文件主名称
        String mainName = FileNameUtil.mainName(file);
        if (file.isDirectory()) {
            //如果遇到.开头的文件夹或包含配置文件中忽略的文件夹
            if(file.getName().startsWith(".")||ignoreDirList.contains(mainName)){
                return;
            }
            final File[] subFiles = file.listFiles();
            if (ArrayUtil.isNotEmpty(subFiles)) {
                for (File tmp : subFiles) {
                    walkFiles(tmp, dirConsumer, fileConsumer);
                }
            }
            dirConsumer.accept(file);
        } else {
            //如果遇到.开头的文件夹或包含配置文件中忽略的文件夹
            if(ignoreFileList.contains(mainName)){
                return;
            }
            fileConsumer.accept(file);
        }
    }
}
